# -*- encoding: utf-8 -*-
"""
# |=========================|
# |    Coding by Noob_0     |
# | Noob_0-main@outlook.com |
# |=========================|

Terminal for Windows 用户界面、应用程序接口

依赖：
    第三方：
        qt_material
        PyQt5
    自定义：
        support

架构：
    ==TextWidget== (QPlainTextEdit)
    --文本框控件--
    methods:
        __init__  初始化
        change_text  检查文本
        cursor_position_changed  光标位置改变对应槽函数

    ==MainWindow==
    --主窗口控制，继承自object--
    methods:
        __init__  初始化
        setupUi  设置UI
        startMainTab  主面板设置
        addTaskTab  增加任务面板
        set_up_menus  菜单设置
        MenubarInsertFilepath  菜单栏：插入文件路径
        MenubarInsertFolderPath  菜单栏：插入文件夹路径
        MenubarInsertSymbol  菜单栏：插入符号
        slot_small_tab  tab设置

    ==TextWidgetIndex==
    --文本索引--
    methods:
        __init__  初始化
        __repr__  print支持

    ==Text==
    --文本内容--
    methods:
        __init__  初始化
        setInput  改变输入
        setOutput  改变输出
        setReminder  改变提示
        getInput  获取输入
        getOutput  获取输出
        getReminder  获取提示

    ==Task==
    --任务--
    methods:
        __init__  初始化
        run  运行
        run_again  重新运行
        stop  停止

====end====
"""
from PyQt5 import QtCore, QtWidgets
# from PyQt5.QtCore import QPoint
from PyQt5.QtGui import QTextCursor

# from PyQt5.QtWidgets import *

from support import *

commands = ('ping', 'explorer')
CommandCompleter(commands)


# 文本索引
# class TextWidgetIndex:
#     # 初始化
#     def __init__(self, block_index: int, str_index: int):
#         self.block_index = block_index
#         self.str_index = str_index
#
#     # print支持
#     def __repr__(self):
#         return str(self.block_index) + str(self.str_index)


class Text:
    class _Line(list):
        def __init__(self, parent):
            super().__init__()
            self.parent = parent

        def __setitem__(self, index, text: str):
            text = str(text)
            super().__setitem__(index, text)
            self.update()

        def __delitem__(self, index):
            super().__delitem__(index)
            self.update()

        def update(self, _obj: str = None):
            if _obj is None:
                self.parent.string = str().join(self)
            else:
                super().__setitem__(slice(len(self)), list(_obj.split('\n')))

    def __init__(self, parent):
        self.parent = parent
        self.string = str()
        self._lines = self._Line(parent=self)

    def __repr__(self):
        return self.string

    def __str__(self):
        return self.string

    def __getitem__(self, index):
        return self.string.__getitem__(index)

    def __setitem__(self, index, text):
        if isinstance(index, int):
            self.string = self.string[:index] + str(text) + self.string[index + 1:]
        elif isinstance(index, slice):
            start = index.start if index.start is not None else 0
            stop = index.stop if index.stop is not None else len(self.string)
            step = index.step if index.step is not None else 1
            if start < 0: start += len(self.string)
            if stop < 0: stop += len(self.string)
            new_str = str()
            i = 0
            for j in range(len(self.string)):
                if start <= j < stop and (j - start) % step == 0:
                    try:
                        new_str += str(text[i])
                        i += 1
                    except IndexError:
                        break
                else:
                    new_str += self.string[j]
            self.string = new_str
        else:
            raise TypeError('index must be a int or slice, not %s' % type(index))
        self.parent_update()

    def __delitem__(self, index):
        if isinstance(index, int):
            if index < 0: index += len(self.string)
            self.string = self.string[:index] + self.string[index + 1:]
        elif isinstance(index, slice):
            start = index.start if index.start is not None else 0
            stop = index.stop if index.stop is not None else len(self.string)
            step = index.step if index.step is not None else 1
            if start < 0: start += len(self.string)
            if stop < 0: stop += len(self.string)
            new_str = str()
            for j in range(len(self.string)):
                if not (start <= j < stop and (j - start) % step == 0):
                    new_str += self.string[j]
            self.string = new_str
        self.parent_update()

    @property
    def lines(self):
        self._lines.update(self.string)
        return self._lines

    def set_text(self, text):
        self.string = str(text)

    def add_text(self, text):
        self.string += str(text)

    def replace(self, _old: (str, list, tuple), _new: str):
        if isinstance(_old, str):
            self.string.replace(_old, _new)
        else:
            for old_text in _old:
                self.string.replace(str(old_text), _new)

    def parent_update(self):
        if isinstance(self.parent, TextWidget):
            self.parent.textUpdate()


# 初始化原函数
# def __init__(self, parent):
#     self.parent: TextWidget = parent
#     self.blocks = []
#     self._reminder: list = []
#     self._output_index: TextWidgetIndex = TextWidgetIndex(0, 0)
#     self._input_index: TextWidgetIndex = TextWidgetIndex(0, 0)
#     self._reminder_index: TextWidgetIndex = TextWidgetIndex(0, 0)

# print支持
# def __repr__(self):
#     return self.getValue()

# 增加提示
# def add_reminder(self, RM):
#     self._reminder.append(RM)

# 文本块切割
# def block_split(self, text):
#     self.blocks = []
#     block = ''
#     for i in text:
#         block += i
#         if i == '\n':
#             self.blocks.append(block)
#             block = ''
#         elif i == text[-1]:
#             self.blocks.append(block)
#             break

# 文本更改
# def change_text(self, text):
#     self.block_split(text)
#     self.setInput(text[3:], TextWidgetIndex(len(self.blocks), len(text) - 4))
#     if (not self.getInput() == '') and (self.getInput()[-1] == '\n'):
#         self.parent.task.run(self.getInput(), name='task_test')

# 获取输出
# def getOutput(self):
#     return self._output

# 获取输入
# def getInput(self):
#     return self._input

# 获取提示
# def getReminder(self):
#     return self._reminder

# 获取值
# def getValue(self):
#     return '{}{}{}'.format(self._output, self._input, self._reminder)

# 获取输出索引
# def get_output_index(self):
#     return self._output_index

# 获取输入索引
# def get_input_index(self):
#     return self._input_index

# 获取提示索引
# def get_reminder_index(self):
#     return self._reminder_index

# 检查是否为输出
# def is_output(self, index: TextWidgetIndex):
#     if 0 <= index.block_index <= self.get_output_index().block_index:
#         if 0 <= index.str_index <= self.get_output_index().str_index + 1:
#             return True
#     return False

# 检查是否为输入
# def is_input(self, index: TextWidgetIndex):
#     if self.get_output_index().block_index <= index.block_index <= self.get_input_index().block_index:
#         if self.get_output_index().str_index + 1 < index.str_index:
#             return True
#     return False

# 检查是否为提示
# def is_reminder(self, index: TextWidgetIndex):
#     if self.get_input_index().block_index <= index.block_index <= self.get_reminder_index().block_index:
#         if self.get_input_index().block_index <= index.str_index <= self.get_reminder_index().str_index + 1:
#             return True
#     return False

# 设置输入
# def setInput(self, value: str, index: TextWidgetIndex):
#     self._input = value
#     self._input_index = index

# 设置提示
# def setReminder(self, value: str, index: TextWidgetIndex):
#     self._reminder = value
#     self._reminder_index = index

# 设置输出
# def setOutput(self, value, index: TextWidgetIndex):
#     self._output = value
#     self._output_index = index


# 文本框控件
class TextWidget(QtWidgets.QPlainTextEdit):
    # 初始化
    def __init__(self, parent, task=None):
        super().__init__(parent)
        self.text: Text = Text(self)
        self.old_text = str(self.text)
        self.locked: bool = False
        self.task = task
        self.setLineWrapMode(self.NoWrap)
        self.moveCursor(QTextCursor.End)
        self.textChanged.connect(self.ifChangeText)
        self.cursorPositionChanged.connect(self.cursor_position_changed)

    def textUpdate(self):
        self.setPlainText(str(self.text))

    def cursor_position_changed(self):
        if self.textCursor().blockNumber() < len(self.text.lines) - 1:
            self.locked = True
        else:
            self.locked = False

    def ifChangeText(self):
        if self.locked:
            self.locked = False
            self.text.set_text(self.old_text)
            self.textUpdate()
            self.update()
            self.locked = True
            self.moveCursor(QTextCursor.End)
        else:
            self.text.set_text(self.toPlainText())
            self.old_text = str(self.text)

    def setText(self, text):
        self.text.set_text(text)
        self.textUpdate()

    # 检查文本
    # def change_text(self):
    #     if isinstance(self.task, Task) and not self.task.state == 'run':
    #         self.text.change_text(self.toPlainText())

    # 光标位置改变对应槽函数
    # def cursor_position_changed(self):
    #     if not self.task.state == 'run':
    #         self.text.change_text(self.toPlainText())
    #         self.index_str = self.textCursor().columnNumber()
    #         self.index_block = self.textCursor().blockNumber()
    #         if self.text.is_input(TextWidgetIndex(self.index_block, self.index_str)):
    #             self.setReadOnly(False)
    #         else:
    #             self.setReadOnly(True)
    #             tc = self.cursorForPosition(QPoint(25, 5))
    #             tc.insertText(" ")
    #             self.moveCursor(QTextCursor.Right)
    #         self.debug = ("is_output:{}\n"
    #                       "output_block_index:{}\n"
    #                       "output_str_index:{}\n"
    #                       "\n"
    #                       "is_input:{}\n"
    #                       "input_block_index:{}\n"
    #                       "imput_str_index:{}\n"
    #                       "\n"
    #                       "is_reminder:{}\n"
    #                       "reminder_block_index:{}\n"
    #                       "reminder_str_index:{}\n"
    #                       "\n"
    #                       "index_block:{}\n"
    #                       "index_str:{}").format(
    #             self.text.is_output(TextWidgetIndex(self.index_block, self.index_str)),
    #             self.text.get_output_index().block_index,
    #             self.text.get_output_index().str_index,
    #             self.text.is_input(TextWidgetIndex(self.index_block, self.index_str)),
    #             self.text.get_input_index().block_index,
    #             self.text.get_input_index().str_index,
    #             self.text.is_reminder(TextWidgetIndex(self.index_block, self.index_str)),
    #             self.text.get_reminder_index().block_index,
    #             self.text.get_reminder_index().str_index,
    #             self.index_str,
    #             self.index_block)


# 主窗口
class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, debug: bool = False):
        super().__init__()
        self.tab = QtWidgets.QWidget()
        # self.text = TextWidget(QtWidgets.QWidget())
        self.central_widget = QtWidgets.QWidget()
        self.verticalTabWidget = QtWidgets.QTabWidget(self.central_widget)
        self.main_task = Task(parent=self, verticalTabWidget=self.verticalTabWidget)
        self.main = QtWidgets.QWidget()
        self._translate = QtCore.QCoreApplication.translate
        self.first = 0
        self.MainWindow = None
        self.tasks = []
        # layout = QtWidgets.QHBoxLayout()
        self.setObjectName("self")
        self.resize(800, 600)
        # self.setLayout(layout)
        self.set_up_menus(self)  # 菜单
        self.setCentralWidget(self.central_widget)
        self.setWindowTitle(self._translate("self", "Terminal for Windows"))
        self.setCentralWidget(self.verticalTabWidget)
        # self.verticalTabWidget.currentChanged.connect(self.slot_task)
        self.verticalTabWidget.addTab(self.main_task.tab_page, "主面板")
        # self.main_task.text_widget.textChanged.connect(self.debug_window_text_change)
        # if debug:
        #     self.debug_window = DebugWindow()
        #     self.debug_window.show()

    # 关于
    def about(self):
        self.incomplete_functions()

    # 创建新任务
    def new_task(self):
        new_task = Task(parent=self.MainWindow, verticalTabWidget=self.verticalTabWidget)
        self.tasks.append(new_task)
        self.verticalTabWidget.addTab(new_task.tab_page, 'name')

    # def debug_window_text_change(self):
    #     self.debug_window.change(self.main_task.text_widget.debug)

    # 设置菜单
    def set_up_menus(self, main_window):
        # 文件路径插入
        menubar_insert_filepath = QtWidgets.QAction('文件路径', main_window)
        menubar_insert_filepath.triggered.connect(self.MenubarInsertFilepath)
        # 文件夹路径插入
        menubar_insert_dirpath = QtWidgets.QAction('文件夹路径', main_window)
        menubar_insert_dirpath.triggered.connect(self.MenubarInsertFolderPath)
        # 符号插入
        menubar_insert_symbol = QtWidgets.QAction('符号', main_window)
        menubar_insert_symbol.triggered.connect(self.MenubarInsertSymbol)
        # 帮助
        menubar_usage = QtWidgets.QAction('使用方法', main_window)
        menubar_usage.triggered.connect(self.usage)
        menubar_problem_solving = QtWidgets.QAction('解决问题', main_window)
        menubar_problem_solving.triggered.connect(self.problem_solving)
        # 关于
        menubar_about = QtWidgets.QAction('关于', main_window)
        menubar_about.triggered.connect(self.about)
        # 导入配置
        menubar_setting_loading = QtWidgets.QAction('导入设置', main_window)
        menubar_setting_loading.triggered.connect(self.setting_loading)
        menubar = main_window.menuBar()  # 声明菜单栏
        # 插入
        menu_insert = menubar.addMenu('插入')
        menu_insert.addAction(menubar_insert_filepath)
        menu_insert.addAction(menubar_insert_dirpath)
        menu_insert.addAction(menubar_insert_symbol)
        # 设置
        menu_set = menubar.addMenu('设置')
        menu_set.addAction(menubar_about)
        menu_set.addAction(menubar_setting_loading)
        # 帮助
        menu_help = menubar.addMenu('帮助')
        menu_help.addAction(menubar_usage)
        menu_help.addAction(menubar_problem_solving)

    # 未完善的功能提示
    def incomplete_functions(self):
        QtWidgets.QMessageBox.warning(QtWidgets.QWidget(self.main),
                                      '警告',
                                      '功能未完善',
                                      QtWidgets.QMessageBox.Yes,
                                      QtWidgets.QMessageBox.Yes)

    def add_text(self, text):
        self.main_task.text_widget.text.add_text(text)

    # 菜单栏功能：插入文件路径
    def MenubarInsertFilepath(self):
        # self.checkTab()
        file_path, _ = QtWidgets.QFileDialog.getOpenFileName(
            self.MainWindow,  # 父窗口对象
            "选择你要插入的文件的路径",  # 标题
            r"c:\\",  # 起始目录
            "所以类型 (*.*)")
        self.add_text('"' + file_path + '"')

    # 菜单栏功能：插入文件夹路径
    def MenubarInsertFolderPath(self):
        # self.checkTab()
        dir_path = QtWidgets.QFileDialog.getExistingDirectory(self.MainWindow, "选择你要插入的文件夹的路径")
        self.add_text('"' + dir_path + '"')

    # 菜单栏功能：插入符号
    def MenubarInsertSymbol(self):
        self.incomplete_functions()

    # 解决问题
    def problem_solving(self):
        self.incomplete_functions()

    # 导入设置
    def setting_loading(self):
        self.incomplete_functions()

    # 使用方法
    def usage(self):
        self.incomplete_functions()


# debug窗口
class DebugWindow(QtWidgets.QDialog):
    # 初始化
    def __init__(self):
        super(DebugWindow, self).__init__()
        self.resize(250, 300)
        self.central_widget = QtWidgets.QWidget()
        self.text = QtWidgets.QPlainTextEdit(parent=self)
        self._translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(self._translate("self", "debugger"))
        self.text.resize(250, 300)

    def change(self, new_value: str):
        self.text.setPlainText(new_value)


# 任务
class Task:
    # 初始化
    def __init__(self, parent, verticalTabWidget):
        self.cmd: CMDPopen = CMDPopen()
        self.state: str = ''
        self.tab_page: QtWidgets.QTabWidget = QtWidgets.QTabWidget(parent=parent)
        self.text_widget: TextWidget = TextWidget(parent=parent, task=self)
        self.layout = QtWidgets.QHBoxLayout()
        self.verticalTabWidget = verticalTabWidget
        # self.set_state('init')
        self.text_widget.setText('>>>\n>>>')
        self.layout.addWidget(self.text_widget)
        self.tab_page.setLayout(self.layout)

    # 补全
    # def completer(self, command):
    #     self.text.add_reminder(CommandCompleter.complete(command))

    # 运行
    # def _run(self, CMD, name):
    #     self.state = 'run'
    #     self.verticalTabWidget.addTab(self.tab_page, name)
    #     self.cmd.command(CMD)
    #     self.CMDPoutput()

    # CMD管道输出
    # def CMDPoutput(self):
    #     self.text.setOutput(self.cmd.wait(), TextWidgetIndex(self.text.get_output_index().block_index,
    #                                                          self.text.get_output_index().str_index))
    #     print(self.cmd.wait())

    # CMD管道输入
    # def CMDPinput(self, value):
    #     self.cmd.command(value)

    # 重新运行
    # def run_again(self):
    #     pass

    # 停止
    # def stop(self):
    #     self.state = 'stop'
    #     self.cmd.kill()

    # def set_state(self, state, **kwargs):
    #     if state == 'init':
    #         self.state = 'init'
    #     elif state == 'wait':
    #         self.state = 'wait'
    #     elif state == 'run':
    #         self.state = 'run'
    #         self._run(self, **kwargs)
    #     elif state == 'stop':
    #         self.state = 'stop'
    #         self.cmd.kill()
